from .error import BiliAPIError
import inspect


class Endpoint:
    """
    Decorator for invoking api.
    """

    def __init__(self, endpoint, method='GET', params=None, index=None, android=False, sign=True, mapping=None,
                 biliapi=None):
        if params is None:
            params = {}
        if mapping is None:
            mapping = {}
        self.endpoint = endpoint
        self.method = method
        self.index = index
        self.android = android
        self.sign = sign
        self.mapping = mapping
        self.params = params
        self.biliapi = biliapi

    def __call__(self, f):
        def wrapped_f(*args, **kwargs):
            # 变量
            params = {}
            i = 0
            # 执行原方法
            f(*args)
            # 取参数、初始化
            keys = inspect.getargspec(f)[0]
            if self.biliapi is None:
                self.biliapi = args[0]._biliapi
                i = 1
                keys = keys[1:]
            for key in keys:
                if key in self.mapping:
                    key = self.mapping[key]
                if i >= len(keys):
                    continue
                params[key] = args[i]
                i += 1
            params = dict(params, **self.params, **kwargs)
            # 请求
            data = self.biliapi.request(url=self.endpoint, params=params, method=self.method, android=self.android,
                                        sign=self.sign)
            if self.biliapi.get_return_url():
                return data
            if isinstance(data, str):
                return data
            if 'code' in data:
                if data['code'] != 0:  # 如果返回错误
                    raise BiliAPIError("Error in invoking api: %s! code: %d, message: %s." % (
                        self.endpoint, data['code'], data['message']))
            if self.index is None:
                return data
            return data[self.index]

        return wrapped_f
